"""
steamlib


Gets information about a player from www.steamcommunity.com using a SteamID
"""

#imports will go here
import re
from utils.web import UrllibBackend
from utils.types import CachedInstancesObject
from BeautifulSoup import BeautifulStoneSoup

#import psyco
#psyco.full()

#Test SteamIDs: STEAM_0:1:8646985,STEAM_0:1:22487776 
downloader = UrllibBackend()
           
class Player(CachedInstancesObject):
    """Receives input for SteamID to recalculate to community id
    and gets profile information from www.steamcommunity.com
    """
    _named = 'steamid'
    _positional = 0

    def init(self, steamid):
        """Init for CachedInstancesObject from utils.types"""
        self.steamid = str(steamid)
        self._soup = None
        response = downloader.async_request("http://steamcommunity.com/profiles/%s?xml=1"
                                            % (self.get_community_id()), callback=self._my_callback)
        
    def _my_callback(self, response):
        """Callback for download(steamid) request"""
        self._soup = BeautifulStoneSoup(response.data)
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup
    
    def get_community_id(self):
        """Converts the SteamId to a community id."""
        if re.match("^STEAM_[0-1]:[0-1]:[0-9]+$", self.steamid) == None:
            raise ValueError("Can not convert %s to a community ID."
                             %(self.steamid))
        else:
            steamid = self.steamid.rsplit(":")
            communityid = int(steamid[1])+int(steamid[2])*2+76561197960265728
            return communityid

    def get_profile_name(self):
        """Gets the user's profile name"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.steamid.string
    
    def get_vac_status(self):
        """Returns whether the player is VAC banned. If yes, returns True; if no,returns False"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            vacbanned = self._soup.profile.vacbanned.string
            if vacbanned == '0':
                return False
            elif vacbanned == '1':
                return True
            else:
                raise Exception("Data could not be retrieved. \
This function may have been deprecated by Steam. \
Check steamlib ChangeLog.")

    def get_online_status(self):
        """Gets the user's online status (online, offline, in-game, etc.)"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.onlinestate.string

    def get_state_message(self):
        """Gets the user's online state message
        (online, last online: x days ago, game name (if in-game), etc.)
        """
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            _status = self.get_online_status() 
            if _status == "in-game":
                return self._soup.profile.statemessage.string.lstrip("In-Game<br  />")
            else:
                return self._soup.profile.statemessage.string.lstrip("<![CDATA[").rstrip("]]")

    def get_steam_rating(self):
        """Gets the user's steam rating. Only numbers now, no ranks."""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.steamrating.string

    def get_hours_played(self):
        """Gets the number of hours the user has played in the past 2 weeks."""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.hoursplayed2wk.string

    def get_join_date(self):
        """Gets the date (member since) the user joined Steam."""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.membersince.string
        
    def get_user_location(self):
        """Gets location (country) set by the user."""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            if self._soup.profile.location.string == " ":
                return "Not Set"
            else:
                return self._soup.profile.location.string

    def get_real_name(self):
        """Gets the user's real name."""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            if self._soup.profile.realname.string == " ":
                return "Not Set"
            else:
                return self._soup.profile.realname.string

    def get_headline(self):
        """Gets the headline of the user's profile"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.profile.headline.string

    def get_summary(self, chars = 0):
        """Gets the user's profile summary. Default = 0 (show all characters)"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            if chars == 0:
                return self._soup.profile.summary.string
            else:
                _string = self._soup.profile.summary.string
                if _string[:chars] == _string:
                    return _string[:chars]
                else:
                    return _string[:chars] + "..."
        
    def joined_group(self,groupname=0):
        """True if user is in specified group, False if user is not in group"""
        if groupname == 0:
            raise ValueError("Argument <groupname> is required. Syntax: joined_group(\"groupname\")")
        else:
            if self._soup.find("error") != None:
                raise ValueError("Can not find SteamID %s." %(self.steamid))
            else:
                check = self._soup.profile.groups.find(name='groupname', text=groupname)
                if check == groupname:
                    return True
                else:
                    return False

class Stats(CachedInstancesObject):
    """Receives input for SteamID to recalculate to community id
    and gets stats from www.steamcommunity.com
    """
    _named = 'steamid'
    _positional = 0

    def init(self, steamid, game=0):
        """Init for CachedInstancesObject from utils.types
        Team Fortress 2 = tf2, Day of Defeat: Source = dods
        """
        self.steamid = str(steamid)
        self._soup = None
        if str.lower(game) != "tf2" and str.lower(game) != "dods":
            raise ValueError("\nSyntax: \
steamlib.Stats(\"<steamid>\",\"<game>\") \n \
        <game> - attribute must be tf2 or dods")
        else:
            if str.lower(game) == "tf2":
                self.game = "TF2"
            if str.lower(game) == "dods":
                self.game = "DOD:S"
            response = downloader.async_request(
                        "http://steamcommunity.com/profiles/%s/stats/%s?xml=1"
                                % (self.get_community_id(), self.game),
                                    callback=self._callback)
            
        
    def _callback(self, response):
        """Callback for download(steamid) request"""
        self._soup = BeautifulStoneSoup(response.data)
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup

    def get_community_id(self, friend_id = 0):
        """Converts the SteamId to a community id."""
        if friend_id != 0:
            if re.match("^STEAM_[0-1]:[0-1]:[0-9]+$", friend_id) == None:
                raise ValueError("Can not convert %s to a community ID."
                                 %(friend_id))
            else:
                steamid = friend_id.rsplit(":")
                communityid = int(steamid[1])+int(steamid[2])*2+76561197960265728
                return communityid
        else:
            if re.match("^STEAM_[0-1]:[0-1]:[0-9]+$", self.steamid) == None:
                raise ValueError("Can not convert %s to a community ID."
                                 %(self.steamid))
            else:
                steamid = self.steamid.rsplit(":")
                communityid = int(steamid[1])+int(steamid[2])*2+76561197960265728
                return communityid

# ------------------------------------------
# Universal Stat Functions (TF2 + DOD:S)
# ------------------------------------------

    def hoursPlayed(self):
        """Hours played"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            return self._soup.playerstats.stats.hoursplayed.string
# -------------------------------------
# Team Fortress 2 Stat Functions
# -------------------------------------

    def accumulatedPoints(self):
        """accumulated points for Team Fortress 2"""
        if self._soup.find("error") != None:
            raise ValueError("Can not find SteamID %s." %(self.steamid))
        else:
            if self.game != "TF2":
                raise ValueError("This function is only available for TF2!")
            else:
                return self._soup.playerstats.stats.accumulatedpoints.string

    def playerClass(self, playerclass=0, attr=0):
        """class = demoman, engineer, heavy, medic, pyro, scout,
        sniper, soldier, spy
        """
        if(str.lower(playerclass) != "demoman" and
           str.lower(playerclass) != "engineer" and
           str.lower(playerclass) != "heavy" and
           str.lower(playerclass) != "medic" and
           str.lower(playerclass) != "pyro" and
           str.lower(playerclass) != "scout" and
           str.lower(playerclass) != "sniper" and
           str.lower(playerclass) != "soldier" and
           str.lower(playerclass) != "spy"):
            raise ValueError("%s is not a valid playerclass!" %(playerclass))
        else:
            i = 0
            classfind = self._soup.playerstats.stats.findall(
                "classdata")
            while (classfind.classdata[i].classname
                   != str.lower(playerclass)):
                i=i+1
            self._soup.playerstats.stats.classdata[i].classname 
            
